package com.ruoyi.framework.interceptor;

import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

/**
 * @author zhou
 * @version V1.0.0
 * @title tianaceae-intelligent
 * @created 2023-3-27 15:50
 * @description $<TODO description purpose>
 **/
@Intercepts({
    @Signature(
        method = "update",
        type = Executor.class,
        args = {MappedStatement.class, Object.class}
    ),
    @Signature(
        method = "query",
        type = Executor.class,
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}
    )
})
public class SaasSchemaInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        final Object[] args = invocation.getArgs();
        // 获取 拦截方法 的参数
        Object parameterObject = args[1];
        // 获取 MappedStatement 对象
        MappedStatement ms = (MappedStatement) args[0];
        //获取到拥有占位符的sql语句
        BoundSql boundSql = ms.getBoundSql(parameterObject);

        String sql = boundSql.getSql();
        System.out.println("拦截前sql :" + sql);

        SQLTableSourceImpl tableSource = getTableNameBySql(sql);
        System.out.println("=============================================================================================");
        System.out.println("tableSource:"+tableSource.toString());
        System.out.println("=============================================================================================");

        return invocation.proceed();
    }

    public static SQLTableSourceImpl getTableNameBySql(String sql) {
        MySqlStatementParser mySqlStatementParser = new MySqlStatementParser(sql);
        SQLStatement statement = mySqlStatementParser.parseStatement();
        SQLTableSourceImpl sqlTableSource = null;
        if(statement instanceof SQLSelectStatement){
            SQLSelect selectQuery = ((SQLSelectStatement)statement).getSelect();
            MySqlSelectQueryBlock sqlSelectQuery = (MySqlSelectQueryBlock)selectQuery.getQuery();

            SQLTableSource tableSource = sqlSelectQuery.getFrom();
            if(tableSource instanceof SQLExprTableSource) {
                SQLExprTableSource sqlTableSource1 = (SQLExprTableSource)sqlSelectQuery.getFrom();
                String tableName = sqlTableSource1.getTableName();
                System.out.println("tableName:"+tableName);
            }
            else if(tableSource instanceof SQLJoinTableSource) {
                SQLJoinTableSource sqlTableSource1 = (SQLJoinTableSource) sqlSelectQuery.getFrom();
                String leftTableName = sqlTableSource1.getLeft().toString();
                String rightTableName = sqlTableSource1.getRight().toString();
            }
            else if(tableSource instanceof SQLSubqueryTableSource)
                sqlTableSource = (SQLSubqueryTableSource) sqlSelectQuery.getFrom();
            else if(tableSource instanceof SQLWithSubqueryClause || tableSource instanceof SQLWithSubqueryClause.Entry)
                sqlTableSource = (SQLWithSubqueryClause.Entry) sqlSelectQuery.getFrom();
        }else if(statement instanceof SQLInsertStatement){
            SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)statement;
            sqlTableSource = sqlInsertStatement.getTableSource();
        }else if(statement instanceof SQLUpdateStatement){
            SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement)statement;
            sqlTableSource = (SQLExprTableSource)sqlUpdateStatement.getTableSource();
        }else if(statement instanceof SQLDeleteStatement){
            SQLDeleteStatement sqlUpdateStatement = (SQLDeleteStatement)statement;
            sqlTableSource = (SQLExprTableSource)sqlUpdateStatement.getTableSource();
        }
        return sqlTableSource;
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
